﻿/*
Copyright (c) 2025 HeZongLun
NahidaProject is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan
PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/

#pragma once

#include <iostream>
#include <string>
#include <map>
#include <functional>
#include <thread>
#include <vector>
#include <sstream>
#include <algorithm>
#include <cstring>

#ifdef _WIN32
#define ExportSymbol  __declspec(dllexport)
#else
#define ExportSymbol
#endif

#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#endif

namespace NahidaProject {
	class ExportSymbol HTTPServer {
	public:
		// HTTP请求结构
		struct HTTPRequest {
			std::string method;
			std::string path;
			std::string version;
			std::map<std::string, std::string> headers;
			std::string body;
			std::map<std::string, std::string> queryParams;
		};

		// HTTP响应结构
		struct ExportSymbol HTTPResponse {
			int statusCode = 200;
			std::string statusText = "OK";
			std::map<std::string, std::string> headers;
			std::string body;

			HTTPResponse() {
				headers["Content-Type"] = "text/html; charset=utf-8";
				headers["Connection"] = "close";
			}
		};

		// 处理器类型定义
		using Handler = std::function<void(const HTTPRequest&, HTTPResponse&)>;

	private:
		int serverSocket;
		bool running;
		std::map<std::string, std::map<std::string, Handler>> routes;
		std::string host;
		int port;

	public:
		HTTPServer(const std::string& host = "127.0.0.1", int port = 8080) : serverSocket(-1), running(false), host(host), port(port) {

#ifdef _WIN32
			WSADATA wsaData;
			WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
		}

		~HTTPServer() {
			StopServer();
#ifdef _WIN32
			WSACleanup();
#endif
		}

		void AddRoute(const std::string& method, const std::string& path, Handler handler);
		void ActionGet(const std::string& path, Handler handler);
		void ActionPost(const std::string& path, Handler handler);
		void ActionPut(const std::string& path, Handler handler);
		void ActionDelete(const std::string& path, Handler handler);

		bool StartServer();
		void StopServer();

	private:
		void ParseRequestLine(const std::string& line, HTTPRequest& request);
		void ParseHeaders(std::istringstream& iss, HTTPRequest& request);
		bool ParseHTTPRequest(const std::string& raw_request, HTTPRequest& request);
		std::string BuildHTTPResponse(const HTTPResponse& response);
		void HandleClient(int clientSocket);
	};
}